package org.setec.manager.stubview;

import org.setec.utils.Utils;
import org.setec.utils.io.Stub;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Iterator;

public class StubViewTransformer {
    
    public String[] getViewHierarchy(Stub stub){

        StringBuffer formattedMethodName = new StringBuffer();
        formattedMethodName.append(stub.getMethodName()).append("(");
        Class[] classes = Utils.objectClasses(stub.getArgs());
        for( int i = 0; i < classes.length; i++ ){
            formattedMethodName.append(classes[i].getName());
            if( i!=(classes.length-1) ){
                formattedMethodName.append(",");
            }
        }
        formattedMethodName.append(")");

        return new String[] { stub.getClassName(), formattedMethodName.toString() };
    }

    public String getDescription(Stub stub){

        StringBuffer result = new StringBuffer();

        int argumentIndex = 1;
        for( Iterator it = Arrays.asList(stub.getArgs()).iterator(); it.hasNext(); ){
            Object arg = it.next();
            result.append("Argument ").append(argumentIndex).append(": ").append(arg.getClass().getName()).append("<br/>");
            try {
                result.append(renderObject(arg));
            } catch (IllegalAccessException e) {

                result.append("Error rendering object <br/>").append("<div><pre>").
                        append(Utils.formatStackTrace(e.getStackTrace())).append("</pre></div>");
            }
        }

        return result.toString();
    }

    private String renderObject(Object object) throws IllegalAccessException {

        StringBuffer result = new StringBuffer();

        Field[] fields = object.getClass().getFields();

        for( Iterator it = Arrays.asList(fields).iterator(); it.hasNext(); ){
            Field field = (Field) it.next();
            result.append(renderField(object, field, 0));
        }

        return object.toString();
    }

    private String renderField(Object object, Field field, int depth) throws IllegalAccessException {

        StringBuffer result = new StringBuffer();

        boolean haveOwnToString = false;
        for( Iterator it = Arrays.asList(field.getClass().getDeclaredMethods()).iterator(); it.hasNext(); ){
            Method method = (Method) it.next();
            if( method.getName().equals("toString") && method.getParameterTypes().length==0 ){
                haveOwnToString = true;
            }
        }

        //indentation
        for( int i = 0; i<depth; i++ ){
            result.append("  ");
        }

        if( haveOwnToString || field.getType().isPrimitive() ){
            result.append(field.get(object));
        } else {
            Field[] supFields = object.getClass().getFields();

            for( Iterator it = Arrays.asList(supFields).iterator(); it.hasNext(); ){
                Field supField = (Field) it.next();
                result.append(renderField(object, field, depth + 1));
            }
        }

        return result.toString();
    }

}
